// 需要动态变化的放在这里，预定义好的放在GeneralConstant中
import {ConfigKey} from "../constant/ConfigConstant";
import Configer from "../frame/apiModel/config/Configer";
import {ColorStr} from "../type/Type";
import {Logger} from "../frame/apiModel/config/Logger";
import {PlayerModel} from "../frame/apiModel/adapterModel/model4/PlayerModel";
import {UnitModel} from "../frame/apiModel/adapterModel/model3/UnitModel";
import {PlayerDataKey} from "../frame/dataSource/DataSource";
import {PlayerFactory} from "../frame/PlayerFactory";
import {CodeUtil} from "../frame/codeAdapter/CodeUtil";
import {TimerControl} from "../controller/TimeController";
import {DataRouter} from "../frame/dataSource/DataRouter";
import {RewardGroupType} from "../frame/dataSource/DataModel";


export class GlobalEnv {
    static get luckyRadix(): number {
        return this._luckyRadix;
    }
    static set luckyRadix(value: number) {
        this._luckyRadix = value;
    }
    static get affixs(): string[] {
        return this._affixs;
    }
    static set affixs(value: string[]) {
        this._affixs = value;
    }

    // 困难需要动态变化
    private static _difficult;

    // 进攻怪波数
    private static _wave = 1;

    // 玩家数奖励幸运值
    private static _luckyRadix = 0;

    // 掉落记录
    private static dropRecord: { [key: string]: boolean } = {};

    // 出怪计时器
    private static _waveTimer: TimerControl;
    // 本局词缀
    private static _affixs: string[] = [];
    // 多面板
    // private static _multiboard: multiboard = CreateMultiboard();
    // 下一波回调
    static nextWaveCallBack: (() => void)[] = [];
    // 游戏是否已经开始
    static bStart: boolean = false;

    // 共享boss的生命值
    static shareBossLife: number = 0;
    static shareBossMaxLife: number = 0;
    static shareBossArr: UnitModel[] = [];

    static boss: UnitModel;

    static allAttackMonster: { [key: string]: number } = {};
    static allMaxAttackNum: number = 0;

    // private static initUnitSRArrs: Map<number, string[]> = new Map<number, string[]>();
    // private static initUnitSSRArrs: Map<number, string[]> = new Map<number, string[]>();
    // private static initAbilityRArrs: Map<number, string[]> = new Map<number, string[]>();
    // private static initAbilitySRArrs: Map<number, string[]> = new Map<number, string[]>();
    static init() {
        PlayerFactory.getInstance().mapAllNotEndPlayingPlayer((player) => {
            player.reflushUUId();
        })
        const playeNum = PlayerFactory.getInstance().getPlayingPlayerNum();
        const luckyRadixs: number[] = Configer.getConfig(ConfigKey.luckyRadixByPlayerNum);
        const luckyRadix = luckyRadixs[playeNum - 1];

        this.reflushMaxAttackNum();

        if (luckyRadix) {
            Logger.toastProduct(`当前玩家数: ${playeNum}`);
            const diffRadixs: number[] = Configer.getConfig(ConfigKey.diffRadixByPlayerNum);
            const diffRadix: number = diffRadixs[playeNum - 1];
            Logger.toastProduct(`难度奖励基数: ${diffRadix}`);
            Logger.toastProduct(`幸运奖励基数: ${luckyRadix}`);
            this.luckyRadix = luckyRadix;
        } else {
            Logger.toastError(`玩家数增强爆率基数不正确，请联系作者修改`);
        }
    }

    static reflushMaxAttackNum() {
        const playerNum = PlayerFactory.getInstance().getPlayingPlayerNum();
        const radixs = Configer.getConfig(ConfigKey.attackMonsterMaxNum) as number[];
        let radix = radixs[playerNum - 1];
        if (radix) {
        } else {
            radix = 0;
        }
        GlobalEnv.allMaxAttackNum = radix;
    }

    static get wave(): number {
        return this._wave;
    }
    static set wave(wave) {
        this._wave = wave;
    }
    static addWave(num: number) {
        const tempWave = GlobalEnv._wave + num
        GlobalEnv._wave = tempWave;
    }

    static get difficult(): number {
        return this._difficult;
    }

    static set difficult(value: number) {
        this._difficult = value;
    }
    static get waveTimer() {
        return this._waveTimer;
    }

    static set waveTimer(value) {
        this._waveTimer = value;
    }

    static addHero(player: PlayerModel, unit: UnitModel | undefined) {
        player.data[PlayerDataKey.hero] = unit
    }

    /**
     * 可能为空
     * 当玩家退出游戏后
     * @param player
     */
    static getHero(player: PlayerModel): UnitModel {
        const hero = player?.data[PlayerDataKey.hero] as UnitModel;
        return hero;
    }
    static isInHeroGroup(unit: UnitModel) {
        const player = PlayerFactory.getInstance().getUnitOwner(unit);
        if (player?.isValid()) {
        } else {
            return false;
        }
        const hero = player.data[PlayerDataKey.hero];
        if (hero === unit) {
            return true
        }
        return false;
    }


    static getPlayerHurts(): { name: string, value: number, id: number }[] {
        const hurts: { name: string, value: number, id: number }[] = [];
        PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
            (player) => {
                const isPlaying = player.isNotEndPlaying();
                const hero = GlobalEnv.getHero(player);
                const isAlive = hero?.isAlive();
                let playerName = '已失败';
                if (isPlaying) {
                    if (isAlive) {
                        playerName = CodeUtil.getColorStr(ColorStr.green, player.name);
                    } else {
                        playerName = CodeUtil.getColorStr(ColorStr.red, player.name);
                    }
                } else {
                    return;
                }
                const playerId = player.playerId;
                const value = player.data[PlayerDataKey.hurtNum];
                const hurt: { name: string, value: number, id: number } = { name: playerName, value: value, id: playerId };
                hurts.push(hurt);
            }
        )
        hurts.sort(
            (a, b) => {
                if (a.value > b.value) {
                    return -1
                }
                if (a.value < b.value) {
                    return 1
                }
                return 0;
            }
        )
        return hurts;
    }

    static addAllAttackMonster(unit: UnitModel) {
        const handleId = unit.getHandleId();
        GlobalEnv.allAttackMonster[handleId] = 1;
    }
    static removeAllAttackMonster(unit: UnitModel) {
        let ret = false;

        const attackMonsters = GlobalEnv.allAttackMonster;
        const handleId = unit.getHandleId();
        if (handleId) {
            attackMonsters[handleId] = undefined;
            return true
        }

        PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
            (player) => {
                if (player?.isValid()) {
                    const temp = player?.removeAttackMonster(unit);
                    if (temp) {
                        ret = true;
                    }
                }
            }
        )

        return ret;
    }
    static getAllMaxAttackMonsterNum() {
        let sum = GlobalEnv.allMaxAttackNum;

        PlayerFactory.getInstance().mapAllNotEndPlayingPlayer((player) => {
            if (player?.isValid()) {
                const size = player?.getMaxAttackMonsterNum();
                sum = sum + size;
            }
        })
        return sum
    }
    static getAllAttackMonsterNum() {
        let sum = CodeUtil.getObjSize(GlobalEnv.allAttackMonster);

        PlayerFactory.getInstance().mapAllNotEndPlayingPlayer((player) => {
            if (player?.isValid()) {
                const size = player?.getAttackMonsterNum();
                sum = sum + size;
            }
        })
        return sum
    }
    static setBox(player: PlayerModel, box: UnitModel) {
        if (player?.isValid()) {
            player.data[PlayerDataKey.box] = box;
        }
    }
    static getBox(player: PlayerModel): UnitModel {
        if (player?.isValid()) {
            const box = player.data[PlayerDataKey.box];
            return box
        }
    }
    static isInBoxGroup(unit: UnitModel) {
        const player = PlayerFactory.getInstance().getUnitOwner(unit);
        if (player?.isValid()) {
            if (unit === player.data[PlayerDataKey.box]) {
                return true
            }
        }
        return false
    }
    static getCheckLose(player: PlayerModel) {
        if (player?.isValid()) {
            const bLose = player.data[PlayerDataKey.bLoseing]
            return bLose;
        }
        return true;
    }
    static setCheckLose(player: PlayerModel, is: boolean) {
        if (player?.isValid()) {
            player.data[PlayerDataKey.bLoseing] = is;
        }
    }
    static getBeWin(player: PlayerModel) {
        if (player?.isValid()) {
            const bWin = player.data[PlayerDataKey.bWin];
            return bWin;
        }
        return false;
    }
    static setBeWin(player: PlayerModel, is: boolean) {
        if (player?.isValid()) {
            player.data[PlayerDataKey.bWin] = is;
        }
    }
    static getBeLose(player: PlayerModel) {
        if (player?.isValid()) {
            const bLose = player.data[PlayerDataKey.bLose];
            return bLose;
        }
        return true;
    }
    static setBeLose(player: PlayerModel, is: boolean) {
        if (player?.isValid()) {
            player.data[PlayerDataKey.bLose] = is;
        }
    }
    static getBeEnd(player: PlayerModel) {
        if (player?.isValid()) {
            return (player.data[PlayerDataKey.bLosed] || player.data[PlayerDataKey.bWined])
        }
        return true
    }
    static getAllBeEnd() {
        let bEnd = true;
        PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
            (player) => {
                const tempEnd = this.getBeEnd(player);
                if (tempEnd) {
                } else {
                    bEnd = false;
                }
            }
        )
        return bEnd;
    }

    static getKillNum(player: PlayerModel) {
        if (player?.isValid()) {
            return player.data[PlayerDataKey.killNum];
        }
        return 0;
    }
    static addKillNum(player: PlayerModel) {
        if (player?.isValid()) {
            player.data[PlayerDataKey.killNum] = player.data[PlayerDataKey.killNum] + 1;
        }
    }
    static addInputNum(player: PlayerModel, id: string, maxNum: number) {
        if (player?.isValid()) {
        } else {
            return true
        }
        if (id) {
        } else {
            return true;
        }
        let num = 0;
        const inputRecord = player.data[PlayerDataKey.inputRecord];
        const recordNum = inputRecord[id];
        if (recordNum) {
            num = num + recordNum
        }
        num = num + 1;
        if (num > maxNum) {
            return false;
        }
        inputRecord[id] = num;
        return true;
    }
    static getTeamFreePlayer(teamId: number) {
        const maxEnemy = Configer.getConfig(ConfigKey.maxEnemys) as number;
        let retPlayer: PlayerModel;
        let minNum = maxEnemy;
        PlayerFactory.getInstance().mapAllPlayer(
            (player) => {
                const tempTeam = player.team;
                if (tempTeam === teamId) {
                    const enemys = player.data[PlayerDataKey.enemyUnits];
                    const keys = Object.keys(enemys);
                    if (keys.length <= minNum) {
                        minNum = keys.length;
                        retPlayer = player;
                    }
                }
            }
        )
        if (retPlayer) {
            return retPlayer;
        }
        Logger.toastError(`敌对怪物数量超出最大值: ${minNum}，请联系作者更改！`)
        // PlayerFactory.getInstance().mapAllPlayer(
        //     (player) => {
        //         const str = JSON.stringify(player.data[PlayerDataKey.enemyUnits])
        //         Logger.toastError(str)
        //         LocalSaveUtil.saveLog(str);
        //     }
        // )
    }
    static getBlongPlayer(unit: UnitModel) {
        let ret: PlayerModel;
        PlayerFactory.getInstance().mapAllPlayer(
            (player) => {
                if (ret) {
                    return;
                }
                const blong = GlobalEnv.isBlongPlayer(unit, player)
                if (blong) {
                    ret = player;
                }
            }
        )
        return ret;
    }
    static isBlongPlayer(unit: UnitModel, player: PlayerModel) {
        const handleId = unit?.getHandleId();
        if (handleId) {
            if (player.data[PlayerDataKey.generateUnitMap][handleId]) {
                return true;
            }
        }
        return  false;
    }

    static checkPlayerDropRecord(player: PlayerModel, dropGroupId: string, dropGroupType: RewardGroupType): number {
        switch (dropGroupType) {
            case RewardGroupType.default:{
                return 1;
            }
            case RewardGroupType.allOnlyOne:{
                if (GlobalEnv.dropRecord[dropGroupId]) {
                    Logger.toastTask(`${dropGroupId} 达到最大掉落次数！`, player);
                    return 0;
                } else {
                    GlobalEnv.dropRecord[dropGroupId] = true;
                    return 1;
                }
            }
            case RewardGroupType.playerOnlyOne:{
                if (player.data[PlayerDataKey.dropRecord][dropGroupId]) {
                    Logger.toastTask(`${dropGroupId} 达到最大掉落次数！`, player);
                    return 0;
                } else {
                    player.data[PlayerDataKey.dropRecord][dropGroupId] = true;
                    return 1;
                }
            }
            case RewardGroupType.mallCumulative:{
                const num = player.getMallItemCount(dropGroupId);
                return num;
            }
            case RewardGroupType.useCumulative:{
                const num = player.getMallItemCount(dropGroupId);
                player.consumMallItemCount(dropGroupId, num);
                return num;
            }
        }
        return 1;
    }

    static getCurrentDiffData() {
        const difficult = GlobalEnv.difficult;
        const difficultDatas = DataRouter.getDifficultDatas();
        if (!CodeUtil.isNull(difficult)) {
            return difficultDatas[difficult]
        }
        return difficultDatas[0]
    }
}